<template>
  <div id="container"></div>
</template>
<script setup>
import { onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

const config = {
  defaultConfig: {
    borderImage: "components/static-image/earth3DNew/opacityMap.png",
    mapImage: "components/static-image/earth3DNew/map_inverted3.jpg",
    pointImage: "components/static-image/earth3DNew/dot.png"
  },
  lineConfig: {
    color: "#2ef266",
    opacity: 1,
    show: true
  },
  pointConfig: {
    color: "#6392a8",
    count: 200,
    size: 22
  }
}

let camera, renderer, controls, earthImg, earthImgData;
const scene = new THREE.Scene();
const textureLoader = new THREE.TextureLoader();
let dotTexture = textureLoader.load("images/dot.png")
let hexagonColor = [0xffffff, 0xffff00];
let hexagon = new THREE.Object3D()
let cloud = new THREE.Object3D()
let coneImg = ["./images/lightray.jpg", "./images/lightray_yellow.jpg"]
const vertexShader = `\n      
  uniform float size;\n      
  uniform float scale;\n      
  varying float opacity;\n\n      
  void main() {\n        
    vec4 mPosition = modelMatrix * vec4( position, 1.0 );\n        
    vec4 mvPosition = viewMatrix * mPosition;\n        
    vec4 mZeroPositon = modelMatrix * vec4(.0, .0, .0, 1.0);\n\n        
    vec3 positionToZero = mPosition.xyz - mZeroPositon.xyz;\n\n        
    vec3 vToEye = cameraPosition - mPosition.xyz;\n        
    opacity = dot(vToEye, positionToZero);\n        gl_PointSize = size * ( scale / -mvPosition.z );\n        gl_Position = projectionMatrix * mvPosition;\n      
  }
`
const fragmentShader = `
  uniform vec3 color;\n      
  uniform sampler2D pointTexture;\n      
  varying float opacity;\n\n      
  void main() {\n        
    if(opacity <= 0.0) {\n          
      gl_FragColor = vec4(color, 0.05);\n        
    } else {\n          
      gl_FragColor = vec4(color, 1.0);\n        
    }\n        \n        
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );\n      
  }
`
onMounted(() => {
  init()
  animate()
  initEarth()
  window.addEventListener("resize", windowResize);
})
function init() {
  // 相机
  const aspect = window.innerWidth / window.innerHeight;
  camera = new THREE.PerspectiveCamera(45, aspect, 1, 20000);
  camera.position.set(0, 2000, -3000);
  // 场景

  // 灯光
  const hemiLight = new THREE.HemisphereLight(0xffffff, 0x999999);
  hemiLight.position.set(0, 20000, 0);
  scene.add(hemiLight);
  // 渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  // 事件控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enablePan = false;
  controls.enableDamping = true;

  document.getElementById("container").appendChild(renderer.domElement);

  const geometry = new THREE.SphereGeometry(999, 100, 100);
  console.log(geometry);
  const material = new THREE.MeshBasicMaterial( { color: 0x000000, depthTest: true } );
  const sphere = new THREE.Mesh( geometry, material );
  scene.add( sphere );
}

function windowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.updateProjectionMatrix();
}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
  controls.update();
}

function initEarth() {
  earthImg = document.createElement("img");
  earthImg.src = "images/earth.jpg";
  earthImg.onload = () => {
    let earthCanvas = document.createElement("canvas");
    let earthCtx = earthCanvas.getContext("2d");
    earthCanvas.width = earthImg.width;
    earthCanvas.height = earthImg.height;
    earthCtx.drawImage(earthImg, 0, 0, earthImg.width, earthImg.height);
    earthImgData = earthCtx.getImageData(0, 0, earthImg.width, earthImg.height);
    // 光锥
    createObjects();
    // 球面打点
    createEarthParticles();
    createEarthHuan()
    animate();
  };
}

function createEarthHuan () {
  let material = new THREE.MeshBasicMaterial({
    color: 0xffffff,
    alphaMap: textureLoader.load("images/huan.png"),
    transparent: true,
    side: THREE.DoubleSide,
    blending: THREE.AdditiveBlending,
    opacity : 0.3
  });
  let hexagonPlane = new THREE.PlaneGeometry(3500, 3500);
  let plan = new THREE.Mesh(hexagonPlane, material);
  scene.add(plan);
}
function createObjects() {
  // 地标及光锥
  for (let i = 0, length = countries.length; i < length; i++) {
    const position = createPosition(countries[i].position);
    const index = Math.floor(Math.random() * 2);
    createHexagon(position, index); // 地标
    createCone(position, index); // 光锥
  }
}

function createHexagon(position, index) {
  const color = 0xff0000;
  let hexagonPlane = new THREE.PlaneGeometry(80, 80);
  let materialPlane = new THREE.MeshBasicMaterial({
    map: textureLoader.load("images/xxxxx.png"),
    transparent: true,
    side: THREE.DoubleSide,
    blending: THREE.AdditiveBlending,
  });
  let circlePlane = new THREE.Mesh(hexagonPlane, materialPlane);
  circlePlane.position.copy(position);
  circlePlane.lookAt(new THREE.Vector3(0, 0, 0));
  hexagon.add(circlePlane);
  scene.add(hexagon);
}

function createCone(position, index) {
  let texture = new THREE.TextureLoader().load(coneImg[index]);
  let material = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    alphaMap: texture,
    transparent: true,
    side: THREE.DoubleSide,
    blending: THREE.AdditiveBlending,
  });
  let height = Math.random() * 800;
  let geometry = new THREE.PlaneGeometry(50, height);
  let matrix1 = new THREE.Matrix4();
  let plane1 = new THREE.Mesh(geometry, material);
  matrix1.makeRotationX(Math.PI / 2);
  matrix1.setPosition(new THREE.Vector3(0, 0, height / -2));
  geometry.applyMatrix4(matrix1);
  let plane2 = plane1.clone();
  plane2.rotation.z = Math.PI / 2;
  plane1.add(plane2);
  plane1.position.copy(position);
  plane1.lookAt(0, 0, 0);
  scene.add(plane1);
}

function createEarthParticles() {
  let positions = []
  let dotMaterial = new THREE.PointsMaterial({
    alphaMap: dotTexture,
    transparent: true,
    depthWrite: false,
    size: 30
  });
  var spherical = new THREE.Spherical();
  spherical.radius = 1000;
  const step = 300;
  for (let i = 0; i < step; i++) {
    let vec = new THREE.Vector3();
    let radians = 1 / Math.cos(Math.abs(i - step / 2) / step * Math.PI); // 每个纬线圈内的角度均分
    for (let j = 0; j < step; j += radians) {
      let c = j / step; // 底图上的横向百分比
      let f = i / step; // 底图上的纵向百分比
      if (isLandByUV(c, f)) {
        // 根据横纵百分比判断在底图中的像素值
        spherical.theta = c * Math.PI * 2 - Math.PI / 2; // 横纵百分比转换为theta和phi夹角
        spherical.phi = f * Math.PI; // 横纵百分比转换为theta和phi夹角
        vec.setFromSpherical(spherical); // 夹角转换为世界坐标
        positions.push(vec.x, vec.y, vec.z);
      }
    }
  }
  const geometry = new THREE.BufferGeometry();
  const vertices = new Float32Array(positions);
  geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
  let particle = new THREE.Points(geometry, dotMaterial);
  scene.add(particle);
}
function isLandByUV(c, f) {
  if (!earthImgData) {
    // 底图数据
    console.error("data error!");
  }
  let n = parseInt(earthImg.width * c); // 根据横纵百分比计算图象坐标系中的坐标
  let o = parseInt(earthImg.height * f); // 根据横纵百分比计算图象坐标系中的坐标
  return 0 === earthImgData.data[4 * (o * earthImgData.width + n)]; // 查找底图中对应像素点的rgba值并判断
}
function createPosition(lnglat) {
  let spherical = new THREE.Spherical();
  spherical.radius = 1010;
  const lng = lnglat[0];
  const lat = lnglat[1];
  // const phi = (180 - lng) * (Math.PI / 180)
  // const theta = (90 + lat) * (Math.PI / 180)
  const theta = (lng + 90) * (Math.PI / 180);
  const phi = (90 - lat) * (Math.PI / 180);
  spherical.phi = phi;
  spherical.theta = theta;
  let position = new THREE.Vector3();
  position.setFromSpherical(spherical);
  return position;
}
var countries = [
  {
    name: "中国",
    position: [116.2, 39.55],
  },
  {
    name: "中非共和国",
    position: [18.35, 4.23],
  },
  {
    name: "智利",
    position: [-70.4, -33.24],
  },
  {
    name: "乍得",
    position: [14.59, 12.1],
  },
  {
    name: "赞比亚",
    position: [28.16, -15.28],
  },
  {
    name: "越南",
    position: [105.55, 21.05],
  },
  {
    name: "约旦",
    position: [35.52, 31.57],
  },
  {
    name: "英属维尔京群岛",
    position: [-64.37, 18.27],
  },
  {
    name: "英国",
    position: [-0.05, 51.36],
  },
  {
    name: "印度尼西亚",
    position: [106.49, -6.09],
  },
  {
    name: "印度",
    position: [77.13, 28.37],
  },
  {
    name: "意大利",
    position: [12.29, 41.54],
  },
  {
    name: "以色列",
    position: [35.12, 31.47],
  },
  {
    name: "伊朗",
    position: [51.3, 35.44],
  },
  {
    name: "伊拉克",
    position: [44.3, 33.2],
  },
  {
    name: "亚美尼亚",
    position: [44.31, 40.1],
  },
  {
    name: "牙买加",
    position: [-76.5, 18.0],
  },
  {
    name: "匈牙利",
    position: [19.05, 47.29],
  },
  {
    name: "新西兰",
    position: [174.46, -41.19],
  },
  {
    name: "新喀里多尼亚",
    position: [166.3, -22.17],
  },
  {
    name: "希腊",
    position: [23.46, 37.58],
  },
  {
    name: "西班牙",
    position: [-3.45, 40.25],
  },
  {
    name: "乌兹别克斯坦",
    position: [69.1, 41.2],
  },
];
</script>